#ifndef BUFFER_H
#define BUFFER_H

#include <vector>
#include <cassert>
#include <string>
#include <string_view>

class Buffer {
    static const size_t kCheapPrepend = 8;      //预留8字节大小的框架
    static const size_t kInitialSize = 1024;    //缓冲区默认大小1KB

public:
    Buffer(size_t initialSize = kInitialSize) : m_buffer(initialSize), m_readIndex(kCheapPrepend), m_writeIndex(kCheapPrepend){
        
    }

    /// @return 返回可读出字节数
    size_t readableBytes() const {
        return m_writeIndex-m_readIndex;
    }

    /// @return 返回可写入字节数
    size_t writableBytes() const {
        return m_buffer.size()-m_writeIndex;
    }

    /// @return 返回预留字节数 
    size_t prependableBytes() const { return m_readIndex;}

    /// @brief 
    /// @return 返回可读起始位置指针
    char* beginRead() {return begin()+m_readIndex;}

    /// @brief beginRead的const类型
    /// @return 返回可读起始位置指针
    const char* beginRead() const {return begin()+m_readIndex;}

    /// @brief 
    /// @return 返回可写起始位置指针
    char* beginWrite() {return begin()+m_writeIndex;}

    /// @brief beginWrite的const类型
    /// @return 返回可写起始位置指针
    const char* beginWrite() const {return begin()+m_writeIndex;}

    ssize_t readFd(int fd, int* saveError);
    ssize_t writeFd(int fd, int* saveError);

    // c风格字符串版本
    // void append(char* buf, size_t len);
    //使用string_view代替
    
    /// @brief 将data数据插入到Buffer中
    /// @param data 需要插入Buffer中的C风格字符串char*或C++风格字符串string
    void append(std::string_view data);

    //复位
    //被取出数据时需要复位
    void retrieve(size_t len);
    void retrieveAll();

    //取出数据
    std::string retrieveAsString(size_t len);
    std::string retrieveAllAsSting();

    void ensureWritableBytes(size_t len);
    void makeSpace(size_t len);

private:
    char* begin() {
        return &(*m_buffer.begin());
    }
    const char* begin() const {
        return &(*m_buffer.begin()); 
    }

private:
    std::vector<char> m_buffer;
    size_t m_readIndex;
    size_t m_writeIndex;
};

#endif